#
# Copyright (C) [2024] Xingyun Integrated Circuit, Inc.
#
#   GreenCode was a private technology asset of Xingyun Integrated Circuit， Inc （Confidential）
#   Author :  Shawn.Tan
#   Date : 2025.10.28
#
#   History : Initial Version 2025.10.28
#
#
import StateTransition
from Enums import EStateElementType

import gpgpu.PcConfig as PcConfig
from base.GenThread import (
    GenThread,
    GenThreadSetupSequence,
)
from gpgpu.StateTransitionHandlerGPGPU import *
from gpgpu.exception_handlers.ExceptionHandlerManagerGPGPU import (
    ExceptionHandlerManagerGPGPU,
)
from gpgpu.exception_handlers.ExceptionsFactoryGPGPU import (
    ExceptionsFactoryGPGPU,
)


class GenThreadSetupSeqGPGPU(GenThreadSetupSequence):
    """Inherit from GenThreadSetupSequence, return GPGPU specific per-thread
    initial information."""

    def __init__(self, gen_thread, name):
        super().__init__(gen_thread, name)

    def setupBootRegion(self):
        """Setup memory region for boot instructions"""
        self.virtualMemoryRequest(
            "PhysicalRegion",
            {
                "RegionType": "BootRegion",
                "Size": PcConfig.get_boot_region_size(),
                "Type": "I",
                "Bank": 0,
            },
        )

    def setupEssentials(self):
        """Setup essentials like key register fields, etc"""
        self.genSequence("InitialSetup")
        self.updateVm()
        self.genThread.installAddressTable()

        no_handler, valid = self.getOption("NoHandler")
        if (not valid) or (not no_handler):
            self.genThread.installHandlers()

        handler_set, valid = self.getOption("handlers_set")
        if valid:
            self.genThread.specifyExceptionHandlerSet(handler_set)

    def getInitialPC(self):
        """Return initial main test PC for the generator thread"""
        return PcConfig.get_initial_pc(self.genThread.genThreadID)

    # Return boot code address for the generator thread
    def getBootPC(self):
        return PcConfig.get_boot_pc(self.genThread.genThreadID)

    def setDefaultStateTransitionHandlers(self):
        """Set the default StateTransitionHandlers to process StateElements of
        each type."""
        StateTransition.setDefaultStateTransitionHandler(
            MemoryStateTransitionHandlerGPGPU(self.genThread),
            EStateElementType.Memory,
        )
        StateTransition.setDefaultStateTransitionHandler(
            VectorRegisterStateTransitionHandlerGPGPU(self.genThread),
            EStateElementType.VectorRegister,
        )
        StateTransition.setDefaultStateTransitionHandler(
            SystemRegisterStateTransitionHandlerGPGPU(self.genThread),
            EStateElementType.SystemRegister,
        )
        StateTransition.setDefaultStateTransitionHandler(
            GprStateTransitionHandlerGPGPU(self.genThread),
            EStateElementType.GPR,
        )
        StateTransition.setDefaultStateTransitionHandler(
            VmContextStateTransitionHandlerGPGPU(self.genThread),
            EStateElementType.VmContext,
        )
        StateTransition.setDefaultStateTransitionHandler(
            PrivilegeLevelStateTransitionHandlerGPGPU(self.genThread),
            EStateElementType.PrivilegeLevel,
        )
        StateTransition.setDefaultStateTransitionHandler(
            PcStateTransitionHandlerGPGPU(self.genThread), EStateElementType.PC
        )
        StateTransition.setDefaultStateTransitionHandler(
            FloatingPointRegisterStateTransitionHandlerGPGPU(self.genThread),
            EStateElementType.FloatingPointRegister,
        )


#  GenThreadGPGPU class
#  GPGPU class representing generator thread
class GenThreadGPGPU(GenThread):
    def __init__(self, gen_id, interface):
        super().__init__(gen_id, interface)
        self.exceptionHandlerManager = ExceptionHandlerManagerGPGPU(self, ExceptionsFactoryGPGPU())
        self.addressTableManager = None
        self.fastMode = False

    # Called to assign sequences to be run at setup stage
    def assignSetupSequences(self):
        self.addSetupSequence(GenThreadSetupSeqGPGPU)

    # Called to install exception handlers.
    def installHandlers(self):
        # generate exception handlers...
        #ToDo Shawn here remove multi instr
        #self.exceptionHandlerManager.run(address_table_manager=self.addressTableManager)

        # assign SystemCallSequence to handle system call
        from gpgpu.SystemCallSequence import SystemCallSequence

        self.systemCallSequence = SystemCallSequence

        # create SelfHostedDebugSequence instance...
        #   from gpgpu.SelfHostedDebugSequence import SelfHostedDebugSequence

    def installAddressTable(self):
        from gpgpu.AddressTable import AddressTableManagerGPGPU

        if self.addressTableManager is None:
            self.addressTableManager = AddressTableManagerGPGPU(self)
        self.addressTableManager.run()
